package com.cakin.javademo;

/**
 * @ClassName: modifiedDemo
 * @Description: 修饰符测试
 * @Date: 2020/6/12
 * @Author: cakin
 */
public class ModifiedDemo {
    // private 访问控制修饰符
    private boolean myFlag;
    // static 非访问控制符
    // final 非访问控制符
    static final double weeks = 9.5;
    // protected 访问控制修饰符
    // static 非访问控制符
    // final 非访问控制符
    protected static final int BOXWIDTH = 42;


    // 它是默认控制修饰符
    String version = "1.5.1";

    // 它是默认控制修饰符
    boolean processOrder() {
        return true;
    }

    private String format;

    // private 必须提供public的get方法和set方法，这样外部就能访问这个变量了，达到数据保护的目的
    // 隐藏类的实现细节和保护类的数据
    public String getFormat() {
        return format;
    }

    public void setFormat(String format) {
        this.format = format;
    }

    public static void main(String[] args) {
        AudioPlayer audioPlayer = new StreamingAudioPlayer();
        audioPlayer.openSpeaker();

    }
    // 不会被序列化
    public transient int limit = 55;
    // 能够被序列化
    public int b;

    // final定义的变量必须要有一个初始值
    final int value = 10;
    // 下面是声明常量的实例
    public static final int BOXWIDTH1 = 6;
    static final String TITLE = "Manager";

    public void changeValue() {
        // 被final修饰的变量不能改变它的值
        // value = 12; //将输出一个错误
    }
}

// private和protected不能修饰接口和接口中的方法
interface MyInterface {
    void run();
}

// 父类
// fianl不能用于继承的父类，这样的话，继承特性将会丢失
class AudioPlayer {
    protected boolean openSpeaker() {
        System.out.println("我是父类");
        return true;
    }

    public final void changeName() {
        // 方法体
    }
}

// 子类
class StreamingAudioPlayer extends AudioPlayer {
    protected boolean openSpeaker() {
        System.out.println("我是子类");
        return true;
    }
    // 父类中的final修饰的方法不能被子类重写
//    public final void changeName(){
//        // 方法体
//    }
}

class InstanceCounter {
    // 类变量
    private static int numInstances = 0;
    private int num = 5;

    protected static int getCount() {
        return numInstances;
    }

    // 静态方法
    private static void addInstance() {
        // 只能用静态变量
        numInstances++;
        // 不能用非静态变量
        // num++;
    }

    // 让对象加1，存储于 numInstances 静态变量当中
    InstanceCounter() {
        InstanceCounter.addInstance();
    }

    public static void main(String[] arguments) {
        System.out.println("Starting with " +
                InstanceCounter.getCount() + " instances");
        for (int i = 0; i < 500; ++i) {
            new InstanceCounter();
        }
        System.out.println("Created " +
                InstanceCounter.getCount() + " instances");
    }
}

/**
 * 1 抽象类不能用来实例化对象，声明抽象类的唯一目的是为了将来对该类进行扩充。
 * <p>
 * 2 一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法，那么该类一定要声明为抽象类，否则将出现编译错误。
 * <p>
 * 3 抽象类可以包含抽象方法和非抽象方法。
 */
// 收买final和abstract是不能同时使用的
// final abstract class Caravan{
abstract class Caravan {
    private double price;
    private String model;
    private String year;

    // 抽象方法
    public abstract void goFast(); //抽象方法

    public abstract void changeColor();

    // 可以定义非抽象方法
    public int add(int num1, int num2) {
        return num1 + num2;
    }
}

class AbstractTest {
    public static void main(String[] args) {
        // 抽象类不能被实例化
        // new Caravan();
    }
}

/**
 * 1 抽象方法是一种没有任何实现的方法，该方法的的具体实现由子类提供。
 *
 * 2 抽象方法不能被声明成 final 和 static。
 *
 * 3 任何继承抽象类的子类必须实现父类的所有抽象方法，除非该子类也是抽象类。
 *
 * 4 如果一个类包含若干个抽象方法，那么该类必须声明为抽象类。
 *
 * 5 抽象类可以不包含抽象方法。
 *
 * 6 抽象方法的声明以分号结尾
 */
// 如果一个类中的含有abstract这个关键字，那么类必须也包含这个关键字
abstract class SuperClass {
    // 抽象方法,抽象方法是一种没有任何实现的方法
    // 抽象方法的声明以分号结尾
    abstract void m();
    // 抽象方法不能被声明成 final 和 static。
    // final abstract void n();
    // 任何继承抽象类的子类必须实现父类的所有抽象方法，除非该子类也是抽象类。
    // abstract void n();
    // 抽象类可以不包含抽象方法。
    int add(){
        return 5;
    }
}

class SubClass extends SuperClass {
    // 实现抽象方法,该方法的的具体实现由子类提供
    void m() {
        System.out.println("实现抽象方法");
    }
}